﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.Serialization;

// requires System.Runtime.Serialization reference

namespace SharpCommunications.Serialization
{
    public class DefaultSerializer : ISharpSerializer
    {
        #region ISharpSerializer Members

        public string Serialize<T>(T obj, Type knownType)
        {
            List<Type> knownTypes = new List<Type> {knownType};

            return Serialize(obj, knownTypes);
        }

        public string Serialize<T>(T obj, List<Type> knownTypes = null)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                Serialize(stream, obj, knownTypes);

                stream.Seek(0, SeekOrigin.Begin);

                using (StreamReader streamReader = new StreamReader(stream))
                {
                    string data = streamReader.ReadToEnd();
                    return data;
                }
            }
        }

        public T Deserialize<T>(string data, Type knownType)
        {
            List<Type> knownTypes = new List<Type> {knownType};

            return Deserialize<T>(data, knownTypes);
        }

        public T Deserialize<T>(string data, List<Type> knownTypes = null)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                using (StreamWriter streamWriter = new StreamWriter(stream))
                {
                    streamWriter.Write(data);
                    streamWriter.Flush();

                    stream.Seek(0, SeekOrigin.Begin);

                    T obj = Deserialize<T>(stream, knownTypes);

                    return obj;
                }
            }
        }

        #endregion
        
        public static void Serialize<T>(Stream stream, T obj, List<Type> knownTypes = null)
        {
            if(knownTypes == null)
            {
                knownTypes = new List<Type>();
            }

            DataContractSerializer serializer = new DataContractSerializer(typeof(T), knownTypes);
            serializer.WriteObject(stream, obj);
        }

        public static T Deserialize<T>(Stream stream, List<Type> knownTypes = null)
        {
            if (knownTypes == null)
            {
                knownTypes = new List<Type>();
            }

            DataContractSerializer serializer = new DataContractSerializer(typeof(T), knownTypes);
            T obj = (T) serializer.ReadObject(stream);
            return obj;
        }



    }
}
